#include <iostream>
#include <memory>
#include <string>
using namespace std;
class Display {
public:
    Display() = default;
    explicit Display(string name):content_(name){
    };
    void show() const;
    ~Display() {
        cout << "Display: " << content_ << "is dealloced ...\n"; 
    }
private:
    string content_;
};

class Microphone {
    public:
    ~Microphone(){
        cout << "Microphone is dealloced ...\n";
    }
};
void Display::show() const {
    cout << content_ << endl;
} 

class Settings {

public:
    Settings() = default;
    explicit Settings(shared_ptr<Display> dis, unique_ptr<Microphone> &mic):dis_(dis), microphone_(std::move(mic)){

    }
    Display *getDisplay() {
        return dis_.get();
    };

    // 通过使用->运算符重载来获取Display
    Display * operator->(){
        return dis_.get();
    }

    ~Settings(){
        cout << "Settings is dealloced ..." << endl;
    }

private:
    std::shared_ptr<Display> dis_;
    std::unique_ptr<Microphone> microphone_;

};

int main(int argc, char const *argv[])
{
   
    {
        shared_ptr<Display> dis = make_shared<Display>("Dell Screen!");
        unique_ptr<Microphone> micro = make_unique<Microphone>();
        /*
        https://stackoverflow.com/questions/74175542/error-call-to-implicitly-deleted-copy-constructor-of-t-unique-ptr
        注意：Settings set = Settings(dis, (micro));这种写法会导致下面的报错，因为这里触发了copy操作，而unique_ptr所在类的copy构造函数被删除了
            /Users/mikewong/Desktop/Project/CppPrimer/src/HighLevel/smart_ponter.cpp:55:18: error: call to implicitly-deleted copy constructor of 'Settings'
                    Settings set = Settings(dis, (micro));
                            ^     ~~~~~~~~~~~~~~~~~~~~~~
            /Users/mikewong/Desktop/Project/CppPrimer/src/HighLevel/smart_ponter.cpp:45:33: note: copy constructor of 'Settings' is implicitly deleted because field 'microphone_' has a deleted copy constructor
                std::unique_ptr<Microphone> microphone_;
                                            ^
            /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/c++/v1/__memory/unique_ptr.h:213:3: note: copy constructor is implicitly deleted because 'unique_ptr<Microphone>' has a user-declared move constructor
            unique_ptr(unique_ptr&& __u) _NOEXCEPT
        */
        Settings set(dis, (micro));
        Display *innerDis = set.getDisplay();
        innerDis->show();

        // 使用对象调用->操作符函数
        Display *innerDis1 = set.operator->();
        innerDis1->show();
        // 使用指针调用->操作符函数
        Settings *set_p = new Settings(dis, (micro));
        Display *innerDis2 = set_p->operator->();
        innerDis2->show();
        delete set_p;

        // 这样创建智能指针的方法不如make_shared的方式更高效【1步VS2步】，同时不如make_shared方法更安全【这种方式可能导致Display被创建但是指针未创建】
        // 但是如果想要自定义deleter方法，那么就必须这样做
        shared_ptr<Display> samsungp = shared_ptr<Display>(new Display("samsung"), [](Display *d){
            std::cout << "custom deleter: " << std::endl;
            delete d;
        });
    }
    // 如果不使用智能指针，那么就要在外部主动对它进行delete操作
    // delete dis;
    
    return 0;
}
